package com.example.ywr.service.impl;

import com.example.ywr.common.PageParam;
import com.example.ywr.common.PageResult;
import com.example.ywr.entity.Order;
import com.example.ywr.repository.OrderRepository;
import com.example.ywr.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * 订单服务实现类
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order create(Order order) {
        // 生成订单编号
        order.setOrderNo(generateOrderNo());
        return orderRepository.save(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order update(Order order) {
        Optional<Order> optional = orderRepository.findById(order.getId());
        if (optional.isPresent()) {
            Order existOrder = optional.get();
            // 更新订单信息
            existOrder.setTotalAmount(order.getTotalAmount());
            existOrder.setPaymentAmount(order.getPaymentAmount());
            existOrder.setShippingFee(order.getShippingFee());
            existOrder.setStatus(order.getStatus());
            existOrder.setPaymentTime(order.getPaymentTime());
            existOrder.setShippingTime(order.getShippingTime());
            existOrder.setReceiveTime(order.getReceiveTime());
            existOrder.setReceiverName(order.getReceiverName());
            existOrder.setReceiverPhone(order.getReceiverPhone());
            existOrder.setReceiverAddress(order.getReceiverAddress());
            existOrder.setNote(order.getNote());
            return orderRepository.save(existOrder);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        Optional<Order> optional = orderRepository.findById(id);
        if (optional.isPresent()) {
            Order order = optional.get();
            order.setIsDeleted(true);
            orderRepository.save(order);
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDelete(List<Long> ids) {
        List<Order> orders = orderRepository.findAllById(ids);
        if (!orders.isEmpty()) {
            orders.forEach(order -> order.setIsDeleted(true));
            orderRepository.saveAll(orders);
            return true;
        }
        return false;
    }

    @Override
    public Order getById(Long id) {
        Optional<Order> optional = orderRepository.findById(id);
        return optional.orElse(null);
    }

    @Override
    public Order getByOrderNo(String orderNo) {
        Optional<Order> optional = orderRepository.findByOrderNoAndIsDeletedFalse(orderNo);
        return optional.orElse(null);
    }

    @Override
    public PageResult<Order> list(PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<Order> page = orderRepository.findAll(pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<Order> listByUserId(Long userId, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<Order> page = orderRepository.findByUserIdAndIsDeletedFalse(userId, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<Order> listByStatus(Integer status, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<Order> page = orderRepository.findByStatusAndIsDeletedFalse(status, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<Order> listByUserIdAndStatus(Long userId, Integer status, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<Order> page = orderRepository.findByUserIdAndStatusAndIsDeletedFalse(userId, status, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<Order> listByCreateTime(LocalDateTime startTime, LocalDateTime endTime, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<Order> page = orderRepository.findByCreateTimeBetweenAndIsDeletedFalse(startTime, endTime, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(Long id, Integer status) {
        int rows = orderRepository.updateStatus(id, status);
        return rows > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateStatus(List<Long> ids, Integer status) {
        int rows = orderRepository.batchUpdateStatus(ids, status);
        return rows > 0;
    }

    /**
     * 生成订单编号
     *
     * @return 订单编号
     */
    private String generateOrderNo() {
        // 生成订单编号：时间戳 + 随机数
        return System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8);
    }
}